package com.hsgene.user.service.impl;

import com.hsgene.common.util.basic.SimpleRegexUtils;
import com.hsgene.common.util.redis.RedisConstants;
import com.hsgene.common.util.result.ApiResult;
import com.hsgene.common.util.result.NullObject;
import com.hsgene.common.util.validation.FieldChecker;
import com.hsgene.generator.dto.GeneratorDto;
import com.hsgene.user.dto.sms.MessageInfoDto;
import com.hsgene.user.exception.UserErrorCode;
import com.hsgene.user.service.SmsService;
import com.hsgene.user.service.api.GeneratorService;
import com.hsgene.user.service.api.MessageService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;

/**
 * 短信ServiceImpl
 *
 * @author wangbing
 * @version 1.0, 2018/7/10
 */
@Service
public class SmsServiceImpl implements SmsService {

    private final static String USER_LOGIN_SMS_CODE = RedisConstants.DEFAULT_REDIS_PREFIX + RedisConstants.COLON_SPLIT + "user_login_sms_code:";

    /**
     * 登录验证码缓存时间，单位：分钟
     */
    private final static long LOGIN_CODE_CACHE_TIME = 3;

    @Value("${template.sms.user.login}")
    private String templateSmsUserLogin;

    @Autowired
    private GeneratorService generatorService;

    @Autowired
    private MessageService messageService;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Override
    public ApiResult<NullObject> sendLoginCode(String phone) {
        // 参数校验
        FieldChecker.checkEmpty(phone, "phone");
        if (!SimpleRegexUtils.isMobile(phone)) {
            return ApiResult.fail(UserErrorCode.USER_PHONE_NOT_FORMAT);
        }
        // 获取验证码
        ApiResult<GeneratorDto> generatorResult = generatorService.getGenerator("sms", null);
        if (!generatorResult.isSucc()) {
            return ApiResult.fail(generatorResult.getError(), generatorResult.getMessage());
        }
        String loginCode = generatorResult.getData().getSerialNumber();
        // 格式化短信内容并发送
        String msgContent = String.format(templateSmsUserLogin, loginCode);
        ApiResult<MessageInfoDto> messageResult = messageService.sendMessage(msgContent, phone);
        if (!messageResult.isSucc()) {
            return ApiResult.fail(messageResult.getError(), messageResult.getMessage());
        }
        // 缓存短信验证码，用于后续用户登录时进行校验
        redisTemplate.opsForValue().set(USER_LOGIN_SMS_CODE + phone, loginCode, LOGIN_CODE_CACHE_TIME, TimeUnit.MINUTES);

        return ApiResult.succ();
    }

    @Override
    public boolean checkLoginVerifyCode(String phone, String loginCode) {
        FieldChecker.checkEmpty(phone, "phone");
        FieldChecker.checkEmpty(loginCode, "loginCode");

        String cacheLoginCode = redisTemplate.opsForValue().get(USER_LOGIN_SMS_CODE + phone);
        boolean isEqual = loginCode.equalsIgnoreCase(cacheLoginCode);
        // 验证成功，删除验证码，防止重复使用
        if (isEqual) {
            redisTemplate.delete(USER_LOGIN_SMS_CODE + phone);
        }
        return isEqual;
    }
}
